/**
 * 2017年3月10日
 */
package cn.edu.bjtu.alex.supervise;

import java.lang.management.ManagementFactory;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Iterator;

import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.DynamicMBean;
import javax.management.InstanceAlreadyExistsException;
import javax.management.IntrospectionException;
import javax.management.InvalidAttributeValueException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanConstructorInfo;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.ReflectionException;

/**
 * @author Alex
 *
 */
public class BaseMBean implements DynamicMBean{
    
	    private MBeanInfo mBeanInfo = null;     
	    private String className;     
	    private String description;     
	    private MBeanAttributeInfo[] attributes;         
	    private MBeanOperationInfo[] operations;     
	    MBeanNotificationInfo[] mBeanNotificationInfoArray;   
	  
	    public BaseMBean() {     
	    	buildDynamicMBean();
	    }     
	  	   
	    final protected void buildDynamicMBean() {     
	        //create constructor     
	    	className = this.getClass().getName();     
	        description = "Simple implementation of a MBean.";     
	          
	        mBeanNotificationInfoArray = new MBeanNotificationInfo[0];   
	        //create attribute  
	        Field[]fields = this.getClass().getDeclaredFields();
	        attributes = new MBeanAttributeInfo[1];
	        for(int i=0;i<1;i++){
	        	try {
					attributes[i] = new MBeanAttributeInfo("inputDir","java.lang.String", "no desc", true,true,false);
				} catch (SecurityException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
	        	
	        }
	        
	        operations = new MBeanOperationInfo[2];       
	        MBeanParameterInfo[] params = null;//no parameter  
	        operations[0] = new MBeanOperationInfo("print", "print something", params, "void", MBeanOperationInfo.INFO);      
	        //operations[1] not use for now
	        mBeanInfo = new MBeanInfo(className, description, attributes, null, operations, mBeanNotificationInfoArray);     
	        ObjectName on;
			try {
				on = new ObjectName("jmx:name="+this.toString());
				getServer().registerMBean(this, on);
			} catch (MalformedObjectNameException | InstanceAlreadyExistsException | MBeanRegistrationException | NotCompliantMBeanException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	      
	    }     
	      
	    //dynamically add a print1 method  
//	    private void dynamicAddOperation() {     
//	        init();     
//	        operations = new MBeanOperationInfo[2];  
//	        buildDynamicMBean();     
//	        operations[1] = new MBeanOperationInfo("print1", "print1(): print the name", null, "void", MBeanOperationInfo.INFO);     
//	        mBeanInfo = new MBeanInfo(className, description, attributes, constructors, operations, mBeanNotificationInfoArray);     
//	    }     
	      
	    @Override  
	    public Object getAttribute(String attribute_name) {  
	        if (attribute_name == null) {  
	            return null;  
	        }  
	        try {
				Field f = this.getClass().getDeclaredField(attribute_name);
				return f.get(this);
			} catch (Exception e) {
			     return null;
			} 
	    }     
	  
	    @Override  
	    public void setAttribute(Attribute attribute) {   
//	        if (attribute == null) {  
//	            return;  
//	        }  
//	          
//	        String Name = attribute.getName();     
//	        Object value = attribute.getValue();     
//	        try {     
//	            if (Name.equals("Name")) {  
//	                // if null value, try and if the setter returns any exception     
//	                if (value == null) {     
//	                    name = null;     
//	                // if non null value, make sure it is assignable to the attribute     
//	                } else if ((Class.forName("java.lang.String")).isAssignableFrom(value.getClass())) {      
//	                    name = (String) value;     
//	                }     
//	            }     
//	        } catch (Exception e) {     
//	            e.printStackTrace();     
//	        }     
	    }     
	  
	    @Override  
	    public AttributeList getAttributes(String[] attributeNames) {     
	        if (attributeNames == null) {  
	            return null;  
	        }  
	          
	        AttributeList resultList = new AttributeList();     
	        // if attributeNames is empty, return anempty result list     
	        if (attributeNames.length == 0) {  
	            return resultList;  
	        }  
	          
	        for (int i = 0; i < attributeNames.length; i++) {     
	            try {     
	                Object value = getAttribute(attributeNames[i]);     
	                resultList.add(new Attribute(attributeNames[i], value));     
	            } catch (Exception e) {     
	                e.printStackTrace();     
	            }     
	        }     
	        return resultList;     
	    }     
	  
	    @Override  
	    public AttributeList setAttributes(AttributeList attributes) {     
	        if (attributes == null) {  
	            return null;  
	        }  
	              
	        AttributeList resultList = new AttributeList();     
	        // if attributeNames is empty, nothing more to do     
	        if (attributes.isEmpty()) {  
	            return resultList;  
	        }  
	          
	        // for each attribute, try to set it and add to the result list if successfull     
	        for (Iterator i = attributes.iterator(); i.hasNext();) {     
	            Attribute attr = (Attribute) i.next();     
	            try {  
	                setAttribute(attr);     
	                String name = attr.getName();     
	                Object value = getAttribute(name);     
	                resultList.add(new Attribute(name, value));     
	            } catch (Exception e) {     
	                e.printStackTrace();     
	            }     
	        }     
	        return resultList;     
	   }     
	      
	    @Override  
	    public Object invoke(String operationName, Object params[], String signature[]) throws MBeanException,ReflectionException {     
	        // Check for a recognized operationname and call the corresponding operation     
//	        if (operationName.equals("print")) {   
//	            System.out.println("Hello, " + name + ", this is HelloDynamic!");    
//	              
//	            //dynamic add a method  
////	            dynamicAddOperation();     
//	            return null;     
//	        } else if (operationName.equals("print1")) {     
//	            System.out.println("dynamically add a print1 method");     
//	            return null;     
//	        } else {     
//	            // unrecognized operation name:  
//	            throw new ReflectionException(new NoSuchMethodException(operationName), "Cannot find the operation " + operationName + " in " + className);     
//	        }     
	    	return null;
	    }     
	  
	    public MBeanInfo getMBeanInfo() {     
	        return mBeanInfo;     
	    }  
	    public final MBeanServer getServer(){
	    	return  ManagementFactory.getPlatformMBeanServer();  
	    }
	    public Object getF(String name){
	    	try {
				return this.getClass().getDeclaredField(name).get(this);
			} catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				return null;
			}
	    }
}
